package com.mjk.common.tools.excel.impl;


import com.mjk.common.base.model.BaseEntity;
import com.mjk.common.tools.excel.IFileImportAndExport;
import com.mjk.common.tools.excel.annotation.ExportFiled;
import com.mjk.common.tools.gson.GsonUtils;
import com.mjk.common.tools.logger.BizLogger;
import com.mjk.common.util.BeanUtils;
import com.mjk.common.util.MapUtils;
import com.mjk.common.util.ObjectUtils;
import com.mjk.common.util.ReflectionUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.core.annotation.AnnotatedElementUtils;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.text.DecimalFormat;
import java.util.*;

/**
 * excel_xlsx 文件导入导出操作
 * @author Administrator
 *
 */
public class XlsxImportAndExportImpl implements IFileImportAndExport {
	private static  int colSizeN = 630;
	private static  int colSizeM = 1000;
	private XSSFWorkbook wb = null;
	private FileOutputStream output = null;
	private XSSFSheet sheet =null;
	@Override
	public <T extends BaseEntity>  List<T> importFile(Class<T> clazz, InputStream xls, String encode){
		try(
				Workbook workbook = new XSSFWorkbook(xls);
		) {
			Sheet sheet1 = workbook.getSheetAt(0);
			Field[] fields = clazz.getDeclaredFields();
			Row header = sheet1.getRow(0);
			Map<String, Integer> headerIndexMap = new HashMap<>();
			Map<String, String> headerMapping = getExportFieldMap(clazz);

			for(int i =0;i<header.getLastCellNum();i++){
				String name = String.valueOf(header.getCell(i)).trim();
				name = MapUtils.getString(headerMapping, name);
				//判断name是否在属性中存在
				for(Field f : fields){
					if(f.getName().equalsIgnoreCase(name)){
						headerIndexMap.put(f.getName(), i);
					}
				}
			}
			List<T> modelList = new ArrayList<>(sheet1.getPhysicalNumberOfRows() * 2);
			for (int i = 1; i < sheet1.getPhysicalNumberOfRows(); i++) {
				T model = clazz.newInstance();
				for (Field field : fields) {
					if(headerIndexMap.containsKey(field.getName())){
						Cell cell = sheet1.getRow(i).getCell(headerIndexMap.get(field.getName()));
						ReflectionUtils.setFieldValue(model, field.getName(), ConvertUtils.convert(parseString(cell),field.getType()));
					}
				}
				modelList.add(model);
			}

			return modelList;
		} catch(Exception e){
			BizLogger.error(e);
		}finally {
			try {
				if(null!=xls)
					xls.close();
			} catch (IOException e) {
				BizLogger.error(e);
			}
		}
		return Collections.emptyList();
	}

	@Override
	public <T extends BaseEntity> void exportFile(List<T> info, String fileName) {
		try(
				XSSFWorkbook wbook = new XSSFWorkbook();
				FileOutputStream fos = new FileOutputStream(fileName);
				) {
			if (info == null) {
				return ;
			}
			int rowSize = info.size() + 1;
			XSSFSheet hSheet = wbook.createSheet();

			XSSFRow headRow = hSheet.createRow(0);
			int colSzie = 0;
			String[] titles = getTitle(info.get(0));
			for(String title : titles){
				XSSFCell cell = headRow.createCell(colSzie);
				cell.setCellValue(new HSSFRichTextString(title));
				hSheet.autoSizeColumn(	colSzie);
				hSheet.setColumnWidth(colSzie, title.length() * colSizeN + colSizeM);
				colSzie++;
			}
			XSSFCellStyle cellStyle = wbook.createCellStyle();
			XSSFDataFormat format = wbook.createDataFormat();
			cellStyle.setDataFormat(format.getFormat("@"));
			for (int i = 2; i < rowSize; i++) {
				if (i >= 65535) {
					int index = i % 65535;
					hSheet = wbook.createSheet("sheet" + index);
				}
				XSSFRow row = hSheet.createRow(i);
				T t = info.get(i - 2);
				int index = 0;
				List<String> values = getItemValue(info.get(0));
				for(String value : values){
					XSSFCell cell = row.createCell(index);
					if (ObjectUtils.isEmpty(value)) {
						cell.setCellValue(new HSSFRichTextString(""));
					} else {
						cell.setCellValue(new HSSFRichTextString(value));
					}
					cell.setCellStyle(cellStyle);
					index++;
				}
			}
			hSheet.addMergedRegion(new CellRangeAddress(0, 0, 0, colSzie - 1));

			wbook.write(fos);
			fos.flush();
			
		} catch (Exception e) {
			BizLogger.error(e);
		}
	}
	
	@Override
	public  <T extends BaseEntity>void exportFile(T t, String fileName, int index, int process) {
		Map<String, Object> params = null;

		try {
			if (0 == index) {
				output = new FileOutputStream(fileName);
				wb = new XSSFWorkbook();
				sheet = wb.createSheet();
				XSSFRow headRow = sheet.createRow(0);
				int colSize = 0;
				String[] titles = getTitle(t);
				for(String title : titles){
					XSSFCell cell = headRow.createCell(colSize);
					cell.setCellValue(new XSSFRichTextString(title));
					colSize++;
				}
			}

			if (index >= 1048576) {
				sheet = wb.createSheet("sheet" + index % 1048576);
				index = index - 1048576;
			}

			XSSFRow row = sheet.createRow(index + 1);
			int cellIndex = 0;
			List<String> values = getItemValue(t);
			for(String value : values){
				XSSFCell cell = row.createCell(cellIndex);
				if (ObjectUtils.isEmpty(value)) {
					cell.setCellValue(new XSSFRichTextString(""));
				} else {
					cell.setCellValue(new XSSFRichTextString(value));
				}
				cellIndex++;
			}
		} catch (Exception e) {
			BizLogger.error(e);
		} finally {
			try {
				if (100 == process) {
					wb.write(output);
					output.flush();

					if (null != wb) {
						wb.close();
					}

					if (null != output) {
						output.close();
					}
				}
			} catch (Exception e) {
				BizLogger.error(e);
			}
		}
	}
	
	@SuppressWarnings("deprecation")
	private static String parseString(Cell cell) {
		if(null==cell) {
			return "";
		}
		CellType cType = cell.getCellType();
		String result = "";
		switch (cType) {
			case NUMERIC://数值处理
				DecimalFormat decimalFormat = new DecimalFormat("###################.###########");
				result =decimalFormat.format(cell.getNumericCellValue());
				break;
			case STRING:
				result = String.valueOf(cell).trim();
				break;
			default:
				break;
		}
		return result;
	}

}
